#include "cnpipe_pipeline.h"
#include "cnpipe_piperangedefiner.h"
#include "geometry/math3d.h"
#include "geometry/wsypath.h"
#include "CNPIPEUtils/checkbendedelements.h"
#include "CNPIPEUtils/calculatebendedpipeofallelements.h"

/** 显示节点管道 */
void CNPIPE_pipeline::showPipeLine()  {
    lines->clear();

    int lineAddCount = 0;

    CNPIPE_pipeRangeDefiner *rd = (CNPIPE_pipeRangeDefiner *)parent->getPipeRangeDefiner();
    qDebug("Episode 1: Start to show pipe line");

    QList<CNPIPE_singleElement *> *elementsArray = rd->getElementsArray();
    QMap<QString, QMap<QString, CNPIPE_singleElement *> *> *oneNodeMoreElements
            = rd->getOneNodeMoreElements();

    QMap<QString, QMap<QString, QList<Vector3D*>*>*> *referenceVectorsOfElements
            = new QMap<QString, QMap<QString, QList<Vector3D*>*>*>();

    int elementsCount = elementsArray->count();

    for (int e = 0; e < elementsCount; e++) {
        CNPIPE_singleElement *element = elementsArray->at(e);
        QString elementName = element->getElementName();

        //获取一个节点中两边的节点号
        QString node1Name = element->getNode1();
        QString node2Name = element->getNode2();


        //获取两个节点中各自所经过的所有单元
        QMap<QString, CNPIPE_singleElement *> *elementsOfNode1
                = oneNodeMoreElements->value(node1Name);
        QMap<QString, CNPIPE_singleElement *> *elementsOfNode2
                = oneNodeMoreElements->value(node2Name);

        //获取两个节点中各自所经过的所有单元号
        QList<QString> eNode1Keys = elementsOfNode1->keys();
        QList<QString> eNode2Keys = elementsOfNode2->keys();

        //获取两个节点中各自所经过的所有单元数目
        int eNode1Count = eNode1Keys.count();
        int eNode2Count = eNode2Keys.count();

        //获取除本地单元外的所有经过这两个节点的单元
        QMap <QString, CNPIPE_singleElement *> *otherElementsOfNode1
                = new QMap <QString, CNPIPE_singleElement *>();
        QMap <QString, CNPIPE_singleElement *> *otherElementsOfNode2
                = new QMap <QString, CNPIPE_singleElement *>();


        for (int e1 = 0; e1 < eNode1Count; e1++) {
            QString sElementName = eNode1Keys.at(e1);
            if (elementName != sElementName){
                CNPIPE_singleElement *sE1 = elementsOfNode1->value(eNode1Keys.at(e1));
                otherElementsOfNode1->insert(sElementName, sE1);
            }
        }

        for (int e2 = 0; e2 < eNode2Count; e2++) {
            QString sElementName = eNode2Keys.at(e2);
            if (elementName != sElementName) {
                CNPIPE_singleElement *sE2 = elementsOfNode2->value(eNode2Keys.at(e2));
                otherElementsOfNode2->insert(sElementName, sE2);
            }
        }

        Vertex3D *node1Position = rd->AdjustSingleNodeNameWithinRange(node1Name);
        Vertex3D *node2Position = rd->AdjustSingleNodeNameWithinRange(node2Name);

        Vector3D *elementDirection = Math3D::direction(node1Position, node2Position);

        QList<Vertex3D*> linePath = QList<Vertex3D*>();
        bool isBended = element->isBended();
        /** 以下是当前单元为弯头的情况，如果为弯头，则会为这些单元新建辅助的单元 */
        if (isBended) {
            QMap<QString, QList<Vector3D *>*> *referenceVectorsOfSingleElement
                    = referenceVectorsOfElements->value(elementName);
            if (referenceVectorsOfSingleElement == NULL) {
                referenceVectorsOfSingleElement = new QMap<QString, QList<Vector3D *>*>();
                referenceVectorsOfElements->insert(elementName, referenceVectorsOfSingleElement);
            }
            QList<Vector3D *> *node1ReferenceVectors
                    = referenceVectorsOfSingleElement->value(node1Name);
            if (node1ReferenceVectors == NULL) {
                node1ReferenceVectors = new QList<Vector3D *>();
                referenceVectorsOfSingleElement->insert(node1Name, node1ReferenceVectors);
            }
            QList<Vector3D *> *node2ReferenceVectors
                    = referenceVectorsOfSingleElement->value(node2Name);
            if (node2ReferenceVectors == NULL) {
                node2ReferenceVectors = new QList<Vector3D *>();
                referenceVectorsOfSingleElement->insert(node2Name, node2ReferenceVectors);
            }


            //左边的弯头数目为1的情况
            if (otherElementsOfNode1->count() == 1) {
                QString leftElementName = otherElementsOfNode1->keys().at(0);
                CNPIPE_singleElement *leftElement = otherElementsOfNode1->value(leftElementName);

                //如果左边的单元不是弯头
                if (!leftElement->isBended()){
                    QMap<QString, CNPIPE_singleNode *> *leftNodes
                            = rd->getBothNodesFromSingleElement(leftElement);

                    QString node1NameOfLeftElement = leftElement->getNode1();
                    QString node2NameOfLeftElement = leftElement->getNode2();

                    /** 获取左边节点（NODE1）中的较近（它本身）和较远的节点名称 */
                    QString furtherNodeName, nearerNodeName;
                    if (node1NameOfLeftElement == node1Name) {
                        nearerNodeName = node1NameOfLeftElement;
                        furtherNodeName = node2NameOfLeftElement;
                    } else { //node2NameOfLeftElement == node2Name
                        nearerNodeName = node2NameOfLeftElement;
                        furtherNodeName = node1NameOfLeftElement;
                    }

                    /** 获取左边节点中两个节点在视图中的位置 */
                    Vertex3D *nearerNodeVertex
                            = rd->AdjustSingleNodeNameWithinRange(nearerNodeName);
                    Vertex3D *furtherNodeVertex
                            = rd->AdjustSingleNodeNameWithinRange(furtherNodeName);


                    Vector3D *leftElementDirection = Math3D::direction(nearerNodeVertex, furtherNodeVertex);
                    Vector3D *node1Direction = Math3D::crossVectors(leftElementDirection, elementDirection);
                    Vector3D *elementDirectionToCenter = Math3D::crossVectors(elementDirection, node1Direction);
                    Vector3D *elementDirectionToReferencePoint
                            = elementDirectionToCenter->normalize()->multiply(-1);
                    Vector3D *referenceVectorOfNode1 = leftElementDirection->normalize()->multiply(-1);
                    Vector3D *reflectionVectorOfNode2
                            = Math3D::computeReflectionVector(referenceVectorOfNode1, elementDirectionToReferencePoint);

                    node1ReferenceVectors->push_back(referenceVectorOfNode1);
                    node2ReferenceVectors->push_back(reflectionVectorOfNode2);
                }
                else {//如果左边的单元是弯头
                    if (referenceVectorsOfElements->value(leftElementName)) {
                        QMap<QString, QList<Vector3D *> *> *referenceVectorOfLeftElement
                                = referenceVectorsOfElements->value(leftElementName);

                        QList<Vector3D *> *leftReferenceVectors
                                = referenceVectorOfLeftElement->value(node1Name);
                        for (int lrv = 0; lrv < leftReferenceVectors->length(); lrv++) {
                            Vector3D *referenceVectorOfNode1 = leftReferenceVectors->at(lrv)->multiply(-1);
                            Vector3D *node1Direction = Math3D::crossVectors(elementDirection, referenceVectorOfNode1);
                            Vector3D *elementDirectionToCenter = Math3D::crossVectors(elementDirection, node1Direction);
                            Vector3D *elementDirectionToReferencePoint
                                    = elementDirectionToCenter->normalize()->multiply(-1);
                            Vector3D *reflectionVectorOfNode2
                                    = Math3D::computeReflectionVector(referenceVectorOfNode1, elementDirectionToReferencePoint);


                            node1ReferenceVectors->push_back(referenceVectorOfNode1);
                            node2ReferenceVectors->push_back(reflectionVectorOfNode2);
                        }
                    } else {
                        //qDebug() << "For the sake of peace of node1";
                    }
                }
            }

            //右边的弯头数目为1的情况
            if (otherElementsOfNode2->count() == 1) {
                QString rightElementName = otherElementsOfNode2->keys().at(0);
                CNPIPE_singleElement *rightElement = otherElementsOfNode2->value(rightElementName);

                //如果右边的单元不是弯头
                if (!rightElement->isBended()){
                    QMap<QString, CNPIPE_singleNode *> *rightNodes
                            = rd->getBothNodesFromSingleElement(rightElement);

                    QString node1NameOfRightElement = rightElement->getNode1();
                    QString node2NameOfRightElement = rightElement->getNode2();

                    /** 获取右边节点（NODE2）中的较近（它本身）和较远的节点名称 */
                    QString furtherNodeName, nearerNodeName;
                    if (node1NameOfRightElement == node2Name) {
                        nearerNodeName = node1NameOfRightElement;
                        furtherNodeName = node2NameOfRightElement;
                    } else {//node2NameOfRightElement == node2Name
                        nearerNodeName = node2NameOfRightElement;
                        furtherNodeName = node1NameOfRightElement;
                    }

                    /** 获取右边节点中两个节点在视图中的位置 */
                    Vertex3D *nearerNodeVertex
                            = rd->AdjustSingleNodeNameWithinRange(nearerNodeName);
                    Vertex3D *furtherNodeVertex
                            = rd->AdjustSingleNodeNameWithinRange(furtherNodeName);

                    Vector3D *rightElementDirection = Math3D::direction(nearerNodeVertex, furtherNodeVertex);
                    Vector3D *node2Direction
                            = Math3D::crossVectors(rightElementDirection, elementDirection);
                    Vector3D *elementDirectionToCenter = Math3D::crossVectors(elementDirection, node2Direction);
                    Vector3D *elementDirectionToReferencePoint
                            = elementDirectionToCenter->normalize()->multiply(-1);
                    Vector3D *referenceVectorOfNode2 = rightElementDirection->normalize()->multiply(-1);
                    Vector3D *reflectionVectorOfNode1
                            = Math3D::computeReflectionVector(referenceVectorOfNode2, elementDirectionToReferencePoint);

                    node1ReferenceVectors->push_back(reflectionVectorOfNode1);
                    node2ReferenceVectors->push_back(referenceVectorOfNode2);
                }
                else {//如果右边的单元是弯头
                    if (referenceVectorsOfElements->value(rightElementName)) {
                        QMap<QString, QList<Vector3D *> *> *referenceVectorOfRightElement
                                = referenceVectorsOfElements->value(rightElementName);

                        QList<Vector3D *> *rightReferenceVectors
                                = referenceVectorOfRightElement->value(node2Name);
                        for (int rrv = 0; rrv < rightReferenceVectors->length(); rrv++) {
                            Vector3D *referenceVectorOfNode2 = rightReferenceVectors->at(rrv)->multiply(-1);
                            Vector3D *node2Direction = Math3D::crossVectors(elementDirection, referenceVectorOfNode2);
                            Vector3D *elementDirectionToCenter = Math3D::crossVectors(elementDirection, node2Direction);
                            Vector3D *elementDirectionToReferencePoint
                                    = elementDirectionToCenter->normalize()->multiply(-1);
                            Vector3D *reflectionVectorOfNode1
                                    = Math3D::computeReflectionVector(referenceVectorOfNode2, elementDirectionToReferencePoint);


                            node1ReferenceVectors->push_back(reflectionVectorOfNode1);
                            node2ReferenceVectors->push_back(referenceVectorOfNode2);
                        }


                    } else {
                        //qDebug() << "For the sake of peace of node2";
                    }
                }
            }
        } else { //The current element has not bended yet.

            linePath.push_back(node1Position);
            linePath.push_back(node2Position);

            node1Position->printSinglePoint("node1");
            node2Position->printSinglePoint("node2");

            WSYPath *line = new WSYPath(linePath);
            lines->push_back(line);

            lineAddCount++;
        }
    }

    //测试每一个弯头是否有切线向量
    qDebug() << "check elements: ";
    CheckBendedElements(referenceVectorsOfElements);

    CalculateBendedPipeOfAllElements(referenceVectorsOfElements, this, parent);
}
